﻿using System;
using System.Xml.Linq;
using NJabber.Stream.Elements;
using NUnit.Framework;

namespace NJabber.Stream.Elements
{
    [TestFixture]
    public class ErrorElementTest : ErrorElementTestBase
    {
        private string errorName = "test-error";
        private string errorDescription = "test-error-description";
        private string errorDescriptionLang = "ts";
        private string errorDetailsName = "error-details";
        private string errorDetailsUri = "error-details-uri";

        public ErrorElementTest() : base("test-error-ns", "", "")
        {
        }

        #region Write method test

        [Test]
        public void Write_NotEmptyErrorName_WritesCorrectXml()
        {
            ErrorElement errorElement = CreateErrorElement(ErrorInfoNamespace);
            XElement expectedElement = CreateErrorXElement(errorName);
            errorElement.ErrorName = errorName;

            VerifyWriteOutput(expectedElement, errorElement);
        }

        [Test]
        public void Write_NotEmptyErrorNameAndDescription_WritesCorrectXml()
        {
            ErrorElement errorElement = CreateErrorElement(ErrorInfoNamespace);
            XElement expectedElement = CreateErrorXElement(errorName, errorDescription, errorDescriptionLang);
            errorElement.ErrorName = errorName;
            errorElement.DescriptionLang = errorDescriptionLang;
            errorElement.ErrorDescription = errorDescription;

            VerifyWriteOutput(expectedElement, errorElement);
        }

        [Test]
        public void Write_NotEmptyErrorNameAndDetails_WritesCorrectXml()
        {
            XmppStreamElement errorDetails = CreateErrorElementDetails(errorDetailsName, errorDetailsUri);
            ErrorElement errorElement = CreateErrorElement(ErrorInfoNamespace);
            XElement expectedElement = CreateErrorXElement(errorName, "", "", errorDetailsName, errorDetailsUri);
            errorElement.ErrorName = errorName;
            errorElement.ErrorDetails = errorDetails;

            VerifyWriteOutput(expectedElement, errorElement);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void Constructor_EmptyErrorNameNotEmptyErrorDetails_ThrowsException()
        {
            XmppStreamElement errorDetails = CreateErrorElementDetails(errorDetailsName, "");
            ErrorElement errorElement = CreateErrorElement(Name);
            errorElement.ErrorDetails = errorDetails;
        }

        #endregion

        #region Equals method test

        [Test]
        public void Equals_DifferentErrorNames_ReturnFalse()
        {
            ErrorElement element1 = CreateErrorElement(ErrorInfoNamespace, "error1");
            ErrorElement element2 = CreateErrorElement(ErrorInfoNamespace, "error2");

            Assert.That(element1.Equals(element2), Is.False);
        }

        [Test]
        public void Equals_SameErrorNames_ReturnsTrue()
        {
            ErrorElement element1 = CreateErrorElement(ErrorInfoNamespace, "error3");
            ErrorElement element2 = CreateErrorElement(ErrorInfoNamespace, "error3");

            Assert.That(element1.Equals(element2), Is.True);
        }

        [Test]
        public void Equals_DifferentErrorDescriptions_ReturnsFalse()
        {
            ErrorElement element1 = CreateErrorElement(ErrorInfoNamespace, errorName, "description1");
            ErrorElement element2 = CreateErrorElement(ErrorInfoNamespace, errorName, "description2");

            Assert.That(element1.Equals(element2), Is.False);
        }

        [Test]
        public void Equals_SameErrorDescriptions_ReturnsTrue()
        {
            ErrorElement element1 = CreateErrorElement(ErrorInfoNamespace, errorName, "description");
            ErrorElement element2 = CreateErrorElement(ErrorInfoNamespace, errorName, "description");

            Assert.That(element1.Equals(element2), Is.True);
        }

        [Test]
        public void Equals_DifferentDescriptionLangs_ReturnsFalse()
        {
            ErrorElement element1 = CreateErrorElement(ErrorInfoNamespace, errorName, errorDescription, "en");
            ErrorElement element2 = CreateErrorElement(ErrorInfoNamespace, errorName, errorDescription, "ua");

            Assert.That(element1.Equals(element2), Is.False);
        }

        [Test]
        public void Equals_SameDescriptionLang_ReturnsTrue()
        {
            ErrorElement element1 = CreateErrorElement(ErrorInfoNamespace, errorName, errorDescription, "tr");
            ErrorElement element2 = CreateErrorElement(ErrorInfoNamespace, errorName, errorDescription, "tr");

            Assert.That(element1.Equals(element2), Is.True);
        }

        #endregion

        private ErrorElement CreateErrorElement(string errorNamespace, string errorName = "", string errorDescription = "", string descriptionLang = "")
        {
            ErrorElement element = CreateStreamElementMock<ErrorElement>(errorNamespace);
            element.ErrorName = errorName;
            element.ErrorDescription = errorDescription;
            element.DescriptionLang = descriptionLang;
            return element;
        }
    }
}
